package ui;

import io.GPSPoint;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;

import math.StatisticProvider;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.event.AxisChangeEvent;
import org.jfree.chart.event.AxisChangeListener;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.DateRange;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;

import actions.Settings;

/**
 * A Panel which shows information about a single run 
 * 
 * @author Oliver Duerr
 */
public class SpeedPanel extends JPanel implements PropertyChangeListener {

	private TimeSeriesCollection dataset;
	
	private static XYPlot plot;

	private JFreeChart chart;

	private ChartPanel chartPanel;

	private final SpeedPanelControler control;

	private ValueAxis domainAxis;

	public SpeedPanel(Map<String, List<GPSPoint>> gpsTracks1, SpeedPanelControler control) {
		this.control = control;
		Settings.getInstance().getPropertyChangeSupport().addPropertyChangeListener(this);
		dataset = createTimeSeries(gpsTracks1);
	    setLayout(new BorderLayout());
	    chart = createChart(dataset);
	    chart.getXYPlot().getDomainAxis().addChangeListener(new MyAxisChangeListener());
	    
	    chartPanel = new ChartPanel(chart);
	    chartPanel.setFillZoomRectangle(true);
	    chartPanel.setMouseWheelEnabled(true);
        add(chartPanel, BorderLayout.CENTER);
        control.createActions(this);
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		if (evt.getPropertyName().equals(Settings.getInstance().LOADED_GPS_FILES)) {
			System.err.println("Redoing the speed panel ");
			Map<String, List<GPSPoint>> gpsTracks = (Map<String, List<GPSPoint>>) evt.getNewValue();
			dataset = createTimeSeries(gpsTracks);
			chart = createChart(dataset);
			domainAxis = chart.getXYPlot().getDomainAxis();
			domainAxis.addChangeListener(new MyAxisChangeListener());
			
			remove(chartPanel);
			//chartPanel.setChart(chart);
			chartPanel = new ChartPanel(chart);
			//chartPanel.setFillZoomRectangle(true);
			chartPanel.setMouseZoomable(false);
			chartPanel.setPopupMenu(null);//new MyPopupMenue());
			chartPanel.setMouseWheelEnabled(true);
		    chartPanel.addMouseListener(new MyMouseListener());
		    add(chartPanel, BorderLayout.CENTER);
		    revalidate();
		    repaint();
		    control.createActions(this);
		}
	}

	private TimeSeriesCollection createTimeSeries(Map<String, List<GPSPoint>> gpsTracks1) {
		List<TimeSeries> series = new ArrayList<TimeSeries>();
		TimeSeriesCollection dataset = new TimeSeriesCollection();
		for (Map.Entry<String, List<GPSPoint>> entry : gpsTracks1.entrySet()) {
			String name = entry.getKey();
			List<GPSPoint> gpsTracks = entry.getValue();
			List<StatisticProvider> providers = control.getStatisticsFactory().getProviders(gpsTracks);
			for (StatisticProvider provider : providers) {
				TimeSeries s = new TimeSeries(new TimeSeriesName(provider.getName(name).getType(), provider.getName(name).getGroupName(), provider.getName(name).getName()));
				provider.setTrack(gpsTracks);
				double[] y = provider.getValues();
				long[] t = provider.getTimes();
				for (int j = 0; j < t.length; j++) {
					s.addOrUpdate(new Second(new Date(t[j])), y[j]);
				}
				dataset.addSeries(s);
			}
		}
		for (TimeSeries timeSeries : series) {
			dataset.addSeries(timeSeries);
		}
		return dataset;
	}

	public static XYPlot getPlot() {
		return plot;
	}
	
	public TimeSeriesCollection getDataset() {
		return dataset;
	}
	
	private static JFreeChart createChart(XYDataset dataset) {

	        JFreeChart chart = ChartFactory.createTimeSeriesChart(
	            "title",  			// title
	            "",             	// x-axis label
	            "",   				// y-axis label
	            dataset,            // data
	            true,               // create legend?
	            true,               // generate tooltips?
	            false               // generate URLs?
	        );

	        chart.setAntiAlias(false);
	        chart.setBackgroundPaint(Color.white);
	        chart.setTitle("");
	        
	        
	        plot = (XYPlot) chart.getPlot();
	        plot.setBackgroundPaint(Color.LIGHT_GRAY.brighter());
	        plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
	        plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
	        plot.setDomainCrosshairVisible(true);
	        plot.setRangeCrosshairVisible(false);
	        //plot.setDomainPannable(true);
	        
	        XYItemRenderer r = plot.getRenderer();
	        if (r instanceof XYLineAndShapeRenderer) {
	            XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
	            renderer.setBaseShapesVisible(true);
	            renderer.setBaseShapesFilled(true);
	            renderer.setDrawSeriesLineAsPath(true);
	        }
	        return chart;
	    }
	 
	 class MyAxisChangeListener implements AxisChangeListener {

		@Override
		public void axisChanged(AxisChangeEvent event) {
			DateAxis axis = (DateAxis) event.getSource();
			DateRange range = (DateRange) axis.getRange();
			long start = range.getLowerMillis();
			long end = range.getUpperMillis();
			//System.out.println("Range changed " + new Date(start) + " " + new Date(end));
			Settings.getInstance().getPropertyChangeSupport().firePropertyChange(Settings.RANGE_CHANGE, null, new long[]{start, end});
		}
		 
	 }
	 
	 class MyPopupMenue extends JPopupMenu {
		 
		 public MyPopupMenue() {
			super();
			add(new JMenuItem("TODO"));
		}
		 
	 }
	 
	 
	 class MyMouseListener extends MouseAdapter {
		 
		private int startX = -1;
		
		public void mousePressed(MouseEvent mouseEvent) {
			 if (SwingUtilities.isRightMouseButton(mouseEvent)) {
				 startX = mouseEvent.getX();
			 }
		 }
		
		public void mouseReleased(MouseEvent mouseEvent) {
			if (SwingUtilities.isRightMouseButton(mouseEvent)) {
				double lowerBound = domainAxis.getLowerBound();
				double upperBound = domainAxis.getUpperBound();
				double deltaMouse = -(mouseEvent.getX() - startX) / (double) getWidth();
				double deltaAxis = (upperBound - lowerBound);
				double lower = lowerBound + deltaAxis * deltaMouse;
				double upper = upperBound + deltaAxis * deltaMouse;
				domainAxis.setRange(lower, upper);
				startX = -1;
			}
		}
	 }
	 
}
